package com.investmenttechnologyservices.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.inject.Inject;
import com.investmenttechnologyservices.model.InstrumentType;
import com.investmenttechnologyservices.model.Region;

public class RegionServiceImpl implements RegionService {

	private static final Logger log = Logger.getLogger(RegionServiceImpl.class.getName());
	
	private DatastoreService ds;
	private HolidayDateService holidayDateService;
	
	@Inject
	RegionServiceImpl(DatastoreService ds, HolidayDateService holidayDateService) {
		this.ds = ds;
		this.holidayDateService = holidayDateService;
	}

	@Override
	public List<Key> getRegionChildren(Key regionKey) {
		
		log.info("getRegionChildren(in): regionKey="+regionKey.toString()+"]");
		
		List<Key> keys = new ArrayList<Key>();
		
		FetchOptions fo = FetchOptions.Builder.withDefaults();

		Filter queryFilter = new FilterPredicate("parentKey",FilterOperator.EQUAL,regionKey);
		Query query = new Query("holidayDate")
			.setFilter(queryFilter);

		List<Entity> result = ds.prepare(query).asList(fo);
		
		if (result.isEmpty()) {
			keys.add(regionKey);
		} else {
			for(Entity iter : result) {
				keys.add(iter.getKey());
			}
		}
		
		log.info("[getRegionChildren(out): keys="+keys.toString()+"]");
		return keys;
	}
	
	@Override
	public Date calculateSettlementDate(Key regionKey, Date tradeDate, InstrumentType instrumentType) {
		log.info("[calculateSettlementDate(in): regionKey="+regionKey.toString()+
				", tradeDate="+tradeDate.toString()+", instrumentType="+instrumentType.toString()+"]");
		Date settlementDate = null;
		try {
			Region region = new Region(ds.get(regionKey));
			Integer defaultSettlementDays = null;
			if (instrumentType != null) {
				Map<InstrumentType, Integer> instrumentTypeSettlementDays = 
					region.getInstrumentTypeSettlementDays();
				if (instrumentTypeSettlementDays != null)
					for (Map.Entry<InstrumentType, Integer> entry : 
						instrumentTypeSettlementDays.entrySet()) {
						if (entry.getKey()==instrumentType) {
							defaultSettlementDays = entry.getValue();
						}
					}
			}
			if (defaultSettlementDays == null) {
				defaultSettlementDays = region.getDefaultSettlementDays();
			}
			settlementDate = holidayDateService.addBusinessDays(regionKey, tradeDate, defaultSettlementDays);

		} catch (EntityNotFoundException ex) {
			// TODO Auto-generated catch block
			ex.printStackTrace();
		}
		log.info("[calculateSettlementDate(out): date="+settlementDate.toString()+"]");
		return settlementDate;
	}
}
